"""
交易统计分析器模块
"""
import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
from loguru import logger
from .analyzer import Analyzer


class TradeStatsAnalyzer(Analyzer):
    """
    交易统计分析器，分析交易的各项统计指标，包括：
    - 日度/月度收益率统计
    - 交易次数统计
    - 多空方向统计
    - 开平仓统计
    - 风险收益指标
    - 交易收益率显著性检验
    - 交易收益率置信区间
    """
    
    def __init__(self, trades, equity_curve):
        """
        初始化交易统计分析器
        
        Parameters
        ----------
        trades : pandas.DataFrame
            交易记录
        equity_curve : pandas.DataFrame
            资金曲线
        """
        super().__init__(trades, equity_curve)
        self._daily_returns = None
        self._monthly_returns = None
        self._trade_returns = None  # 每笔交易的收益率
        self._stats = None
    
    def _calculate_trade_returns(self):
        """
        计算每笔交易（开平对）的收益率
        
        Returns
        -------
        pandas.Series
            每笔交易的收益率序列
        """
        if self._trades.empty:
            return pd.Series()
            
        # 按symbol分组处理每个品种的交易
        all_trade_returns = []
        
        for symbol in self._trades['symbol'].unique():
            symbol_trades = self._trades[self._trades['symbol'] == symbol].copy()
            
            # 确保交易按时间排序
            symbol_trades = symbol_trades.sort_values('datetime')
            
            # 初始化变量
            open_price = None
            open_direction = None
            open_volume = None
            
            # 遍历交易记录，配对开平仓
            for _, trade in symbol_trades.iterrows():
                if trade['offset'] == '开':
                    open_price = trade['price']
                    open_direction = trade['direction']
                    open_volume = trade['volume']
                elif trade['offset'] == '平' and open_price is not None:
                    # 计算收益率
                    if open_direction == 1:  # 多头
                        returns = (trade['price'] - open_price) / open_price
                    else:  # 空头
                        returns = (open_price - trade['price']) / open_price
                    
                    all_trade_returns.append(returns)
                    
                    # 重置开仓变量
                    open_price = None
                    open_direction = None
                    open_volume = None
        
        return pd.Series(all_trade_returns)
    
    def _calculate_trade_stats(self):
        """
        计算交易收益率的统计指标，包括显著性检验和置信区间
        
        Returns
        -------
        dict
            统计结果
        """
        if self._trade_returns is None or len(self._trade_returns) == 0:
            return {}
            
        stats_result = {}
        
        # 基本统计量
        stats_result['trade_returns_mean'] = self._trade_returns.mean()
        stats_result['trade_returns_std'] = self._trade_returns.std()
        stats_result['trade_returns_count'] = len(self._trade_returns)
        
        # 显著性检验（双尾t检验，原假设：均值为0）
        t_stat, p_value = stats.ttest_1samp(self._trade_returns, 0)
        stats_result['t_statistic'] = t_stat
        stats_result['p_value'] = p_value
        stats_result['is_significant'] = p_value < 0.05
        
        # 计算95%置信区间
        ci = stats.t.interval(
            alpha=0.95,  # 95%置信水平
            df=len(self._trade_returns)-1,  # 自由度
            loc=self._trade_returns.mean(),  # 样本均值
            scale=stats.sem(self._trade_returns)  # 标准误
        )
        stats_result['confidence_interval'] = ci
        
        return stats_result
    
    def analyze(self):
        """
        分析回测结果
        
        Returns
        -------
        dict
            分析结果
        """
        # 计算每日收益率
        self._daily_returns = self._calculate_daily_returns()
        
        # 计算每月收益率
        self._monthly_returns = self._calculate_monthly_returns()
        
        # 计算交易收益率
        self._trade_returns = self._calculate_trade_returns()
        
        # 计算统计指标
        self._stats = self._calculate_stats()
        
        # 添加交易统计结果
        self._stats.update(self._calculate_trade_stats())
        
        return self._stats
    
    def _calculate_daily_returns(self):
        """
        计算每日收益率
        
        Returns
        -------
        pandas.Series
            每日收益率序列
        """
        daily_equity = self._equity_curve['equity'].resample('D').last().dropna()
        daily_returns = daily_equity.pct_change().fillna(0)
        return daily_returns
    
    def _calculate_monthly_returns(self):
        """
        计算每月收益率
        
        Returns
        -------
        pandas.Series
            每月收益率序列
        """
        monthly_equity = self._equity_curve['equity'].resample('M').last().dropna()
        monthly_returns = monthly_equity.pct_change().fillna(0)
        return monthly_returns
    
    def _calculate_stats(self):
        """
        计算统计指标
        
        Returns
        -------
        dict
            统计指标
        """
        stats = {}
        
        # 计算每日收益率统计
        if self._daily_returns is not None and len(self._daily_returns) > 0:
            stats['daily_mean'] = self._daily_returns.mean()
            stats['daily_std'] = self._daily_returns.std()
            stats['daily_positive'] = (self._daily_returns > 0).sum() / len(self._daily_returns)
            stats['daily_negative'] = (self._daily_returns < 0).sum() / len(self._daily_returns)
            stats['daily_best'] = self._daily_returns.max()
            stats['daily_worst'] = self._daily_returns.min()
        
        # 计算每月收益率统计
        if self._monthly_returns is not None and len(self._monthly_returns) > 0:
            stats['monthly_mean'] = self._monthly_returns.mean()
            stats['monthly_std'] = self._monthly_returns.std()
            stats['monthly_positive'] = (self._monthly_returns > 0).sum() / len(self._monthly_returns)
            stats['monthly_negative'] = (self._monthly_returns < 0).sum() / len(self._monthly_returns)
            stats['monthly_best'] = self._monthly_returns.max()
            stats['monthly_worst'] = self._monthly_returns.min()
        
        # 计算交易统计
        if not self._trades.empty:
            stats['trade_count'] = len(self._trades)
            
            # 按品种统计
            instrument_counts = self._trades['symbol'].value_counts()
            stats['instruments'] = instrument_counts.to_dict()
            
            # 按方向和开平统计
            direction_offset_counts = self._trades.groupby(['direction', 'offset']).size()
            stats['direction_offset'] = direction_offset_counts.to_dict()
        
        # 计算索提诺比率（假设无风险利率为0，目标收益率为0）
        if self._daily_returns is not None and len(self._daily_returns) > 0:
            downside_returns = self._daily_returns[self._daily_returns < 0]
            if len(downside_returns) > 0 and downside_returns.std() > 0:
                sortino_ratio = self._daily_returns.mean() / downside_returns.std() * np.sqrt(252)
                stats['sortino_ratio'] = sortino_ratio
            else:
                stats['sortino_ratio'] = float('inf')
        
        return stats
    
    def plot(self, figsize=(12, 8)):
        """
        绘制交易指标分析图表
        
        Parameters
        ----------
        figsize : tuple, optional
            图表大小，默认为(12, 8)
            
        Returns
        -------
        matplotlib.figure.Figure
            图表对象
        """
        if self._results is None:
            logger.warning("请先调用analyze方法")
            return None
        
        fig, axes = plt.subplots(3, 1, figsize=figsize)
        
        # 绘制每日收益率
        if self._daily_returns is not None:
            axes[0].bar(self._daily_returns.index, self._daily_returns * 100, color='blue', alpha=0.6, label='每日收益率(%)')
            axes[0].axhline(y=0, color='r', linestyle='-', alpha=0.3)
            axes[0].set_title('每日收益率')
            axes[0].set_ylabel('收益率(%)')
            axes[0].grid(True)
            axes[0].legend()
        
        # 绘制每月收益率
        if self._monthly_returns is not None:
            axes[1].bar(self._monthly_returns.index, self._monthly_returns * 100, color='green', alpha=0.6, label='每月收益率(%)')
            axes[1].axhline(y=0, color='r', linestyle='-', alpha=0.3)
            axes[1].set_title('每月收益率')
            axes[1].set_ylabel('收益率(%)')
            axes[1].grid(True)
            axes[1].legend()
        
        # 绘制交易频率
        if not self._trades.empty:
            # 按日期计算交易次数
            trade_counts = self._trades.set_index('datetime').resample('D').size().fillna(0)
            axes[2].bar(trade_counts.index, trade_counts, color='purple', alpha=0.6, label='每日交易次数')
            axes[2].set_title('交易频率')
            axes[2].set_ylabel('交易次数')
            axes[2].set_xlabel('时间')
            axes[2].grid(True)
            axes[2].legend()
        
        # 添加统计指标文本
        plt.figtext(0.01, 0.01, self._get_stats_text(), fontsize=10)
        
        plt.tight_layout()
        plt.subplots_adjust(bottom=0.2)
        
        return fig
    
    def _get_stats_text(self):
        """
        获取统计指标文本
        
        Returns
        -------
        str
            统计指标文本
        """
        if self._stats is None:
            return ""
            
        text = "--- 收益率统计 ---\n"
        
        if 'daily_mean' in self._stats:
            text += f"平均每日收益率: {self._stats['daily_mean']:.2%}\n"
            text += f"每日收益率标准差: {self._stats['daily_std']:.2%}\n"
            text += f"正收益天数比例: {self._stats['daily_positive']:.2%}\n"
            text += f"负收益天数比例: {self._stats['daily_negative']:.2%}\n"
            text += f"最佳单日收益: {self._stats['daily_best']:.2%}\n"
            text += f"最差单日收益: {self._stats['daily_worst']:.2%}\n"
        
        if 'monthly_mean' in self._stats:
            text += "\n--- 月度统计 ---\n"
            text += f"平均每月收益率: {self._stats['monthly_mean']:.2%}\n"
            text += f"每月收益率标准差: {self._stats['monthly_std']:.2%}\n"
            text += f"正收益月数比例: {self._stats['monthly_positive']:.2%}\n"
            text += f"负收益月数比例: {self._stats['monthly_negative']:.2%}\n"
            text += f"最佳单月收益: {self._stats['monthly_best']:.2%}\n"
            text += f"最差单月收益: {self._stats['monthly_worst']:.2%}\n"
        
        if 'trade_count' in self._stats:
            text += "\n--- 交易统计 ---\n"
            text += f"总交易次数: {self._stats['trade_count']}\n"
            
            if 'direction_offset' in self._stats:
                text += "\n开平统计:\n"
                for (direction, offset), count in self._stats['direction_offset'].items():
                    direction_text = "多" if direction == 1 else "空"
                    text += f"{direction_text}{offset}: {count}次\n"
        
        if 'sortino_ratio' in self._stats:
            text += "\n--- 风险调整收益 ---\n"
            text += f"索提诺比率: {self._stats['sortino_ratio']:.2f}\n"
        
        # 添加交易收益率统计信息
        if 'trade_returns_mean' in self._stats:
            text += "\n--- 交易收益率统计 ---\n"
            text += f"平均收益率: {self._stats['trade_returns_mean']:.2%}\n"
            text += f"收益率标准差: {self._stats['trade_returns_std']:.2%}\n"
            text += f"交易次数: {self._stats['trade_returns_count']}\n"
            text += f"t统计量: {self._stats['t_statistic']:.4f}\n"
            text += f"p值: {self._stats['p_value']:.4f}\n"
            text += f"是否显著: {'是' if self._stats['is_significant'] else '否'}\n"
            text += f"95%置信区间: [{self._stats['confidence_interval'][0]:.2%}, {self._stats['confidence_interval'][1]:.2%}]\n"
        
        return text
